package gruppo12.msp;

import com.google.android.maps.GeoPoint;

import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Toast;
import java.io.IOException;
import java.util.List;
import java.util.Locale;

import gruppo12.msp.data.ConnessioneGoogle;
import gruppo12.msp.elaboration.Elaborazione;
import gruppo12.msp.elaboration.Pianificazione;

/**
 * <p>
 * Classe che implementa l'interfaccia relativa alla visualizzazione del
 * percorso
 * </p>
 * 
 * @author Duca Antonio, Festa Jacopo, Fiorilli Domenico, Granese Dante, Lemma
 *         Saverio, Lombardi Marco e Pierno Fiore
 * 
 */
public class VisualizzaPercorsoActivity extends MapActivity {

	MapView myMapView = null;
	MapController myMC = null;
	GeoPoint geoPoint;
	GeoPoint geoPoint2;
	Elaborazione elaborazione;
	Pianificazione pianificazione;

	class MapOverlay extends com.google.android.maps.Overlay {
		public boolean Draw(Canvas canvas, MapView mapview, boolean shadow,
				long when) {
			super.draw(canvas, mapview, shadow);

			/* Traduzione pixel geopoint dello schermo */
			Point screenPts = new Point();
			myMapView.getProjection().toPixels(geoPoint2, screenPts);
			return true;
		}

		/*
		 * Metodo che, al touch su un punto qualsiasi della mappa, consente di
		 * visualizzare delle informazioni relative al luogo corrispondente
		 */
		public boolean onTouchEvent(MotionEvent event, MapView mapview) {
			/* Avviene quando l'utente solleva il dito */
			if (event.getAction() == MotionEvent.ACTION_DOWN) {
				GeoPoint p = myMapView.getProjection().fromPixels(
						(int) event.getX(), (int) event.getY());

				Geocoder geocoder = new Geocoder(getApplicationContext(),
						Locale.getDefault());
				try {
					List<Address> addresses = geocoder.getFromLocation(
							p.getLatitudeE6() / 1E6, p.getLongitudeE6() / 1E6,
							1);
					String add = "";
					if (addresses.size() > 0) {
						for (int i = 0; i < addresses.get(0)
								.getMaxAddressLineIndex(); i++) {
							add += addresses.get(0).getAddressLine(i) + "\n";
						}
					}
					Toast.makeText(getBaseContext(), add, Toast.LENGTH_SHORT)
							.show();
				} catch (IOException e) {
					Toast.makeText(getBaseContext(), e.getMessage(),
							Toast.LENGTH_SHORT).show();
				}
			} else
				return false;
			return false;
		}
	}

	/**
	 * <p>
	 * Metodo invocato quando viene chiamata per la prima volta l'activity
	 * </p>
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);

		/* Dichiarazioni */
		Intent intent;
		LocationManager locationManager;
		String context;

		/* Recupero dei dati della precedente schermata */
		intent = getIntent();
		String pkg = getPackageName();
		elaborazione = (Elaborazione) intent.getSerializableExtra(pkg
				+ ".elaborazione");

		/* Associazione con gli oggetti grafici dell'xml */
		setContentView(R.layout.visualizzapercorso);
		myMapView = (MapView) findViewById(R.id.mapviewpercorso);

		/* Inizializzazione variabili */
		geoPoint = null;
		myMapView.setSatellite(false);
		context = Context.LOCATION_SERVICE;
		locationManager = (LocationManager) getSystemService(context);

		/* Caso GPS attivo */
		if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {

			Criteria criteria = new Criteria();
			criteria.setAccuracy(Criteria.ACCURACY_FINE);
			criteria.setAltitudeRequired(false);
			criteria.setBearingRequired(false);
			criteria.setCostAllowed(true);
			criteria.setPowerRequirement(Criteria.POWER_LOW);

			String provider = locationManager.getBestProvider(criteria, true);
			/* Recupero la posizione attuale */
			Location location = locationManager.getLastKnownLocation(provider);

			/* Caso posizione rilevata */
			try {
				locationManager.requestLocationUpdates(provider, 0, 0,
						locationListener);
				updateWithNewLocation(location);
			}

			/* Caso posizione non rilevata */
			catch (Exception e) {
				Toast.makeText(
						VisualizzaPercorsoActivity.this,
						"POSIZIONE NON RILEVATA! Impossibile caricare il percorso!",
						Toast.LENGTH_SHORT).show();
				Log.i("" + location.getLatitude(), "" + location.getLongitude());
			}
		}

		/* Caso GPS disattivo */
		else
			Toast.makeText(VisualizzaPercorsoActivity.this,
					"GPS DISABILITATO! Impossibile caricare il percorso!",
					Toast.LENGTH_SHORT).show();

	}

	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}

	/* Listener del GPS */
	private final LocationListener locationListener = new LocationListener() {

		/* Notifica la lettura di una nuova posizione */
		@Override
		public void onLocationChanged(Location location) {
			updateWithNewLocation(location);

		}

		/* Notifica che il GPS e' stato disabilitato. */
		@Override
		public void onProviderDisabled(String provider) {
			updateWithNewLocation(null);

		}

		/* Notifica che il GPS e' stato abilitato */
		@Override
		public void onProviderEnabled(String provider) {
			// TODO Auto-generated method stub

		}

		/* Notifica un cambio di stato del GPS */
		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			// TODO Auto-generated method stub

		}

	};

	/*
	 * Metodo che consente di aggiornare la posizione dell'utente sulla mappa
	 * durante il percorso
	 */
	private void updateWithNewLocation(Location location) {

		/*
		 * Aggiunta dell'indicatore di posizione (funzionalita'info luogo al
		 * touch)
		 */
		MapOverlay mapOverlay = new MapOverlay();
		List<Overlay> listOfOverlays = myMapView.getOverlays();
		listOfOverlays.clear();
		listOfOverlays.add(mapOverlay);

		double latitudine = location.getLatitude();
		double longitudine = location.getLongitude();

		String latitudineS = String.format("%.6f", latitudine);
		String longitudineS = String.format("%.6f", longitudine);

		String posizioneCorrente = "(" + latitudineS + "," + longitudineS + ")";

		/*
		 * In GeoPoint, il primo termine e' la latitudine, il secondo la
		 * longitudine. La partenza corrisponde alla posizione attuale
		 * dell'utente, l'arrivo al pdi scelto dall'itinerario
		 */
		String pairs[] = ConnessioneGoogle.getDirectionData(posizioneCorrente,
				elaborazione.getPdi().getPosizione().toBracketsString());
		String[] lngLat = pairs[0].split(",");

		/* Aggiorna il marker della mappa */
		myMapView = (MapView) findViewById(R.id.mapviewpercorso);
		myMapView.invalidate();

		/*
		 * Coordinate del punto di partenza, creo un nuovo oggetto GeoPoint
		 * impostando latitudine e longitudine
		 */
		GeoPoint startGP = new GeoPoint(
				(int) (Double.parseDouble(lngLat[1]) * 1E6),
				(int) (Double.parseDouble(lngLat[0]) * 1E6));

		myMC = myMapView.getController();
		geoPoint = startGP;
		myMC.setZoom(16);
		myMapView.getOverlays().add(new DirectionPathOverlay(startGP, startGP));

		/* Navigazione del percorso */
		GeoPoint gp1;
		GeoPoint gp2 = startGP;

		for (int i = 1; i < pairs.length; i++) {
			lngLat = pairs[i].split(",");
			gp1 = gp2;

			/*
			 * Coordinate del punto di arrivo, creo un nuovo oggetto GeoPoint
			 * impostando latitudine e longitudine
			 */
			gp2 = new GeoPoint((int) (Double.parseDouble(lngLat[1]) * 1E6),
					(int) (Double.parseDouble(lngLat[0]) * 1E6));
			myMapView.getOverlays().add(new DirectionPathOverlay(gp1, gp2));

		}

		myMapView.getOverlays().add(new DirectionPathOverlay(gp2, gp2));

		/* Animazione della mappa sul punto di partenza */
		myMapView.getController().animateTo(geoPoint);

		/* Resa della mappa cliccabile e zoomabile */
		myMapView.setClickable(true);
		myMapView.setBuiltInZoomControls(true);

		/* Controllo dello lo zoom direttamente sulla mappa */
		myMapView.displayZoomControls(true);

		/*
		 * Inserimento marcatori per il punto di partenza e il punto di arrivo
		 */
		Drawable drawableStart = this.getResources().getDrawable(
				R.drawable.android_pos); /*
										 * Icona per il punto di partenza
										 * dell'utente
										 */
		Drawable drawableFinish = this.getResources().getDrawable(
				R.drawable.arrivo); /* Icona per il punto di arrivo */

		CustomItemizedOverlay itemizedOverlayStart = new CustomItemizedOverlay(
				drawableStart, this);
		CustomItemizedOverlay itemizedOverlayFinish = new CustomItemizedOverlay(
				drawableFinish, this);

		OverlayItem overlayitem1 = new OverlayItem(startGP, "Partenza", null);
		OverlayItem overlayitem2 = new OverlayItem(gp2, "Arrivo", elaborazione
				.getPdi().getNome());

		itemizedOverlayStart.addOverlay(overlayitem1);

		itemizedOverlayFinish.addOverlay(overlayitem2);

		/* Aggiungo gli overlay ottenuti alla mappa */
		myMapView.getOverlays().add(itemizedOverlayStart);
		myMapView.getOverlays().add(itemizedOverlayFinish);
	}
}